package xyz.labmem.lipx.core.tool

import java.util.*


class ConsoleTable {

    companion object {
        var SbcMode=false
        private val HALF_ROW_LINE: Char = '-'
        private val FULL_ROW_LINE: Char = '－'
        private val COLUMN_LINE: Char = '|'
        private val CORNER: Char = '+'

        //半角模式空格的unicode码
        private val HALF_SPACE: Char = '\u0020'

        //全角模式空格的unicode码
        private val FULL_SPACE: Char = '\u3000'
        private val LF: Char = '\n'
        private val SPACE: Char = ' '
        private val EMPTY: String = ""
        fun create(): ConsoleTable {
            return ConsoleTable().setSbcMode(SbcMode)
        }

        /**
         * 重复字符
         *
         * @param c     字符
         * @param count 重复次数
         */
        fun repeat(c: Char, count: Int): String {
            if (count <= 0) {
                return EMPTY
            }

            val result = CharArray(count)
            for (i in 0 until count) {
                result[i] = c
            }
            return String(result)
        }

        /**
         * 转成全角字符
         *
         * @param input 字符
         */
        fun toSbc(input: String): String {
            val c = input.toCharArray()
            for (i in c.indices) {
                if (c[i] == ' ') {
                    c[i] = '\u3000'
                } else if (c[i] < '\u007f') {
                    c[i] = (c[i].code + 65248).toChar()
                }
            }
            return String(c)
        }

    }

    //全角模式
    private var sbcMode = true

    //表格头信息
    private val headerList: MutableList<List<String>> = ArrayList()

    //表格体信息
    private val bodyList: MutableList<List<String>> = ArrayList()

    //每列最大字符个数
    private var columnCharCount: MutableList<Int>? = null

    /**
     * 设置是否使用全角模式
     *
     * @param sbcMode 是否全角模式
     */
    fun setSbcMode(sbcMode: Boolean): ConsoleTable {
        this.sbcMode = sbcMode
        return this
    }

    /**
     * 添加表头
     *
     * @param titles 列名
     */
    fun addHeader(vararg titles: String): ConsoleTable {
        if (columnCharCount == null) {
            columnCharCount = ArrayList(Collections.nCopies(titles.size, 0))
        }
        val headers: MutableList<String> = ArrayList()
        fillColumns(headers, titles)
        headerList.add(headers)
        return this
    }

    /**
     * 添加表体
     *
     * @param values 列值
     */
    fun addBody(vararg values: String): ConsoleTable {
        val bodies: MutableList<String> = ArrayList()
        bodyList.add(bodies)
        fillColumns(bodies, values)
        return this
    }

    /**
     * 填充表头或者表体
     *
     * @param columns 被填充列表
     * @param values  填充值
     */
    private fun fillColumns(columns: MutableList<String>, values: Array<out String>) {
        for (i in values.indices) {
            var column = values[i]
            if (sbcMode) {
                column = toSbc(column)
            }
            columns.add(column)
            var width = column.length
            if (!sbcMode) {
                val sbcCount = nonSbcCount(column)
                width = (width - sbcCount) * 2 + sbcCount
            }
            if (width > columnCharCount!![i]) {
                columnCharCount!![i] = width
            }
        }
    }

    /**
     * 获取表格字符串
     */
    override fun toString(): String {
        val sb = StringBuilder()
        fillBorder(sb)
        fillRows(sb, headerList)
        fillBorder(sb)
        fillRows(sb, bodyList)
        fillBorder(sb)
        return sb.toString()
    }

    /**
     * 填充表头或者表体信息（多行）
     *
     * @param sb   内容
     * @param list 表头列表或者表体列表
     */
    private fun fillRows(sb: StringBuilder, list: List<List<String>>) {
        for (row in list) {
            sb.append(COLUMN_LINE)
            fillRow(sb, row)
            sb.append(LF)
        }
    }

    /**
     * 填充一行数据
     *
     * @param sb  内容
     * @param row 一行数据
     */
    private fun fillRow(sb: StringBuilder, row: List<String>) {
        val size = row.size
        var value: String
        for (i in 0 until size) {
            value = row[i]
            sb.append(if (sbcMode) FULL_SPACE else HALF_SPACE)
            sb.append(value)
            val length = value.length
            val sbcCount = nonSbcCount(value)
            if (sbcMode && sbcCount % 2 == 1) {
                sb.append(SPACE)
            }
            sb.append(if (sbcMode) FULL_SPACE else HALF_SPACE)
            val maxLength = columnCharCount!![i]
            val doubleNum = 2
            if (sbcMode) {
                for (j in 0 until (maxLength - length + (sbcCount / doubleNum))) {
                    sb.append(FULL_SPACE)
                }
            } else {
                for (j in 0 until (maxLength - ((length - sbcCount) * doubleNum + sbcCount))) {
                    sb.append(HALF_SPACE)
                }
            }
            sb.append(COLUMN_LINE)
        }
    }

    /**
     * 填充边框
     *
     * @param sb StringBuilder
     */
    private fun fillBorder(sb: StringBuilder) {
        sb.append(CORNER)
        for (width in columnCharCount!!) {
            sb.append(if (sbcMode) repeat(FULL_ROW_LINE, width + 2) else repeat(HALF_ROW_LINE, width + 2))
            sb.append(CORNER)
        }
        sb.append(LF)
    }

    /**
     * 打印到控制台
     */
    fun print() {
        print(this)
    }

    /**
     * 半角字符数量<br></br>
     * 英文字母、数字键、符号键
     *
     * @param value 字符串
     */
    private fun nonSbcCount(value: String): Int {
        var count = 0
        for (element in value) {
            if (element < '\u007f') {
                count++
            }
        }
        return count
    }


}